package cn.bluethink.eguan.core.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.bluethink.eguan.core.entity.EgFactionEntity;
import cn.bluethink.eguan.core.mapper.EgFactionMapper;
import cn.bluethink.eguan.model.core.EgAcount;
import cn.bluethink.eguan.model.core.EgConfigInfo;
import cn.bluethink.eguan.model.core.EgFaction;
import cn.bluethink.eguan.model.core.EgOType;
import cn.bluethink.eguan.model.core.EgObject;
import cn.bluethink.eguan.model.core.EgRole;
import cn.bluethink.eguan.model.core.EgScope;
import cn.bluethink.eguan.model.core.EgTask;
import cn.bluethink.eguan.model.core.EgUser;
import cn.bluethink.eguan.result.PageInfo;
import cn.bluethink.eguan.utils.IdMakerUtils;
import tk.mybatis.mapper.entity.Example;

/**
 * 门派业务层
 * 
 * @author 苏州中科蓝迪公司所有(c)2016-2021
 * @version 0.1.0
 * @brief 数据处理协同工作平台（DCPP）
 * @note 修订历史： 1、wanglei于2018/10/13设计并构建初始版本v0.1.0
 *       2、wanglei于2018/12/10添加门派充值的金币流通记录
 */
@Service
public class EgFactionService extends AEgPosObjectService {

    @Autowired
    private EgFactionMapper factionMapper;

    @Autowired
    private EgConfigInfo configInfo;

    @Autowired
    private EgMemberService memberService;

    @Autowired
    private EgAcountService acountService;

    @Autowired
    private EgUserService userService;

    @Autowired
    private EgBtsService btsService;

    @Autowired
    private EgTavernService tavernService;

    @Autowired
    private EgStaffService staffService;

    @Autowired
    private EgTaskService taskService;

    @Autowired
    private EgCommentService commentService;

    @Autowired
    private EgFileService fileService;

    @Autowired
    private EgBagService bagService;

    private IdMakerUtils idMakerUtil = new IdMakerUtils();

    public EgFactionService() {
        super();
    }

    @Override
    public Integer posOtype() {
        return EgOType.FACTION;
    }

    @Override
    public EgObject pos(Long posid) throws Exception {
        return this.getById(posid);
    }

    /**
     * 创建门派
     * 
     * @param name
     * @param icon
     * @param uid
     * @param f_id
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public EgFaction create(String name, String icon, Long uid, String f_id) throws Exception {
        // 创建门派之前先创建门派唯账户,账户名同门派名
        EgAcount acount = acountService.create(name + "的账户");
        if (acount == null) {
            return null;
        }
        EgFaction faction = new EgFaction(idMakerUtil.nextId(), name, icon);
        faction.setAcount(acount);
        // 门派创始人默认为当前登录用户
        faction.setUser(new EgUser(uid, null, null));
        EgFactionEntity entity = new EgFactionEntity(faction, f_id);
        int insertCount = factionMapper.insertSelective(entity);
        return insertCount > 0 ? faction : null;
    }

    /**
     * 删除门派(包括门派的所有内容) 主键删除先后顺序问题：揭榜者-悬赏任务-关键项-工作任务-评论-通用任务-文件-伙计-驿馆-门派成员-门派-包裹-账户
     * 
     * @param fid
     * @param uid
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Boolean delete(Long fid, Long uid) throws Exception {
        // 1 存储所有通用任务的发布地点
        Set<Long> posOids = new HashSet<>();
        posOids.add(fid);
        // 获取该门派下所有的驿馆
        List<Long> tavernIds = tavernService.egidsByFid(fid);
        if (tavernIds != null && tavernIds.size() > 0) {
            posOids.addAll(tavernIds);
        }
        // 2 查询所有的悬赏任务
        List<EgTask> rewardTasks = taskService.queryByOtypeAndPos(EgOType.REWARD_TASK, posOids);
        if (rewardTasks != null && rewardTasks.size() > 0) {
            List<Long> rewardTaskIds = rewardTasks.stream().map(o -> o.getId()).collect(Collectors.toList());
            // 2.1 删除所有的领取者
            // 2.2 删除所有的悬赏任务
            // 2.3 删除所有的交流区内容
            if (commentService.queryByRootObjs(EgOType.REWARD_TASK, rewardTaskIds) > 0) {
                if (!commentService.delByRootObjs(EgOType.REWARD_TASK, rewardTaskIds)) {
                    throw new RuntimeException("删除失败，请重试！");
                }
            }
        }
        // 3 查询所有的工作任务
        List<EgTask> okrTasks = taskService.queryByOtypeAndPos(EgOType.OKR_TASK, posOids);
        if (okrTasks != null && okrTasks.size() > 0) {
            List<Long> okrTaskIds = okrTasks.stream().map(o -> o.getId()).collect(Collectors.toList());
            // 3.1 删除所有的关键项
            // 3.2 删除所有的工作任务
            // 3.3 删除所有的评论
            if (commentService.queryByRootObjs(EgOType.OKR_TASK, okrTaskIds) > 0) {
                if (!commentService.delByRootObjs(EgOType.OKR_TASK, okrTaskIds)) {
                    throw new RuntimeException("删除失败，请重试！");
                }
            }
            // 3.4 删除所有上传的文件
            if (fileService.queryByOtypeAndPos(EgOType.OKR_TASK, okrTaskIds) > 0) {
                if (!fileService.delByOtypeAndPos(EgOType.OKR_TASK, okrTaskIds)) {
                    throw new RuntimeException("删除失败，请重试！");
                }
            }
        }
        // 4 逻辑删除所有的通用任务
        List<EgTask> taskList = new ArrayList<>();
        taskList.addAll(rewardTasks);
        taskList.addAll(okrTasks);
        if (taskList != null && taskList.size() > 0) {
            if (!taskService.deltaskList(taskList)) {
                throw new RuntimeException("删除失败，请重试！");
            }
        }
        // 5 删除驿馆伙计
        if (!staffService.delStaffByEgIds(tavernIds)) {
            throw new RuntimeException("删除失败，请重试！");
        }
        // 获取驿馆对应的所有包裹列表
        List<Long> bagIds = tavernService.bagsByFid(fid);
        // 6 删除门派下所有驿馆
        if (tavernIds != null && tavernIds.size() > 0) {
            if (!tavernService.delTavernByFid(fid)) {
                throw new RuntimeException("删除失败，请重试！");
            }
        }
        // 7 删除门派所有成员
        if (!memberService.del(fid)) {
            throw new RuntimeException("删除失败，请重试！");
        }
        // 获取门派的账户ID,防止门派删除后，记录缺失
        Long acountId = getAcountByFid(fid);
        // 8 删除门派
        if (factionMapper.deleteByPrimaryKey(fid) == 0) {
            throw new RuntimeException("删除失败，请重试！");
        }
        // 9 删除驿馆的包裹
        if (bagIds != null && bagIds.size() > 0) {
            if (!bagService.delBagsByEgIds(bagIds)) {
                throw new RuntimeException("删除失败，请重试！");
            }
        }
        // 10 删除门派账户
        if (acountId != null && acountId > 0) {
            if (!acountService.del(acountId)) {
                throw new RuntimeException("删除失败，请重试！");
            }
        }
        // 更新当前用户的位置到江湖中
        if (!userService.updatePos(uid, EgOType.JIANGHU, 0L)) {
            throw new RuntimeException("删除失败，请重试！");
        }
        return true;
    }

    /**
     * 更新门派的基本信息
     * 
     * @param oldFaction
     * @param upFaction
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public EgFaction update(EgFaction oldFaction, EgFaction upFaction) throws Exception {
        // 更新门派图标
        String oldIcon = oldFaction.getIcon();
        String icon = upFaction.getIcon();
        if (StringUtils.isNotBlank(icon) && StringUtils.isNotBlank(oldIcon) && !icon.equals(oldIcon)) {
            oldFaction.setIcon(icon);
        }
        // 更新门派名称
        String oldName = oldFaction.getName();
        String name = upFaction.getName();
        if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(oldName) && !name.equals(oldName)) {
            oldFaction.setName(name);
        }
        // 更新门派的季度年的开始月份
        Integer oldBmonth = oldFaction.getBmonth();
        Integer bmonth = upFaction.getBmonth();
        if (bmonth != null && oldBmonth != null && !bmonth.equals(oldBmonth)) {
            oldFaction.setBmonth(bmonth);
        }
        // 更新操作
        EgFactionEntity entity = new EgFactionEntity(oldFaction, null);
        int updateCount = factionMapper.updateByPrimaryKeySelective(entity);
        return updateCount > 0 ? entity.createFaction() : null;
    }

    /**
     * 根据主键获取门派基本信息(名称，图标)
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    public EgFaction getById(Long fid) throws Exception {
        EgFactionEntity entity = factionMapper.selectByPrimaryKey(fid);
        if (entity == null) {
            return null;
        }
        EgFaction faction = new EgFaction(fid, entity.getName(), entity.getIcon());
        return faction;
    }

    /**
     * 根据corpid查询门派信息
     * 
     * @param f_id
     * @return
     * @throws Exception
     */
    public EgFaction queryByfId(String f_id) throws Exception {
        // 创建查询条件
        Example example = new Example(EgFactionEntity.class);
        example.and().andEqualTo("f_id", f_id);
        EgFactionEntity entity = factionMapper.selectOneByExample(example);
        return entity != null ? entity.createFaction() : null;
    }

    /**
     * 根据主键获取门派详情(包括门派账户详情，门派的帮主基本信息)
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    public EgFaction detail(Long fid) throws Exception {
        EgFactionEntity entity = factionMapper.selectByPrimaryKey(fid);
        if (entity == null) {
            return null;
        }
        EgFaction faction = entity.createFaction();
        // 获取门派账户详情(包含账户金币)
        EgAcount acount = acountService.query(entity.getAcount());
        if (acount != null) {
            faction.setAcount(acount);
        }
        // 获取门派的帮主信息(基本信息)
        EgUser cheaf = memberService.queryByRole(fid, (EgRole.CHEAF | EgRole.MEMBER));
        if (cheaf != null) {
            cheaf = userService.getUser(cheaf.getId(), false);
            if (cheaf != null) {
                faction.setUser(new EgUser(cheaf.getId(), cheaf.getName(), cheaf.getAvatar()));
            }
        }
        return faction;
    }

    /**
     * 由门派ID获取门派的账户ID
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    public Long getAcountByFid(Long fid) throws Exception {
        EgFactionEntity entity = factionMapper.selectByPrimaryKey(fid);
        return entity != null ? entity.getAcount() : 0L;
    }

    /**
     * 根据门派的ID获取季度年的开始月份
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    public Integer getBmonthByFid(Long fid) throws Exception {
        EgFactionEntity entity = factionMapper.selectByPrimaryKey(fid);
        return entity == null ? 1 : entity.getBmonth();
    }

    /**
     * 根据当前用户查询其所属的门派列表（包括江湖）
     * 
     * @param uid
     * @return
     * @throws Exception
     */
    public PageInfo<EgObject> myfaction(Long uid) throws Exception {
        // 返回结果
        List<EgObject> result = new ArrayList<>();
        // 查询用户所属门派列表
        List<EgFactionEntity> entities = factionMapper.queryFactions(uid);
        // 返回江湖信息
        EgObject jianghu = new EgObject(0L, configInfo.jianghu().getName(), new EgOType(EgOType.JIANGHU, null));

        PageInfo<EgFactionEntity> oldPageInfo = new PageInfo<>(entities);
        oldPageInfo.setPageSize(oldPageInfo.getPageSize() + 1);
        oldPageInfo.setTotal(oldPageInfo.getTotal() + 1);

        if (entities != null && entities.size() > 0) {
            for (EgFactionEntity entity : entities) {
                EgFaction faction = new EgFaction(entity.getFid(), entity.getName(), entity.getIcon());
                faction.setBmonth(entity.getBmonth());
                result.add(faction);
            }
        }
        // 没有隶属的门派，直接返回江湖
        result.add(jianghu);
        return new PageInfo<>(result, oldPageInfo);
    }

    /**
     * 移交门派帮主身份
     * 
     * @param user
     * @param toUser
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Boolean transfer(Long fid, EgUser user, EgUser toUser) throws Exception {
        // 门派中默认成员角色，帮主角色，副帮主角色
        EgRole memberRole = configInfo.role(EgRole.MEMBER).get(EgScope.FACTION);
        EgRole cheafRole = configInfo.role(EgRole.CHEAF).get(EgScope.FACTION);
        EgRole viceCheafRole = configInfo.role(EgRole.VICE_CHEAF).get(EgScope.FACTION);
        // 获取门派中帮主的角色
        EgRole userRole = user.getRole();
        // "异或"去除原来，"或"得到最终，并更新
        userRole.xor(cheafRole);
        userRole.or(memberRole);
        user = memberService.update(fid, user.getId(), userRole.getRid(), userRole.getPurview());
        if (user == null) {
            throw new RuntimeException("移交门派帮主失败！");
        }
        // 获取被移交成员的原有的角色
        EgRole toUserRole = toUser.getRole();
        // 如果为副帮主，"异或"去除原来，"或"得到最终
        if ((toUserRole.getRid() & EgRole.VICE_CHEAF) > 0) {
            toUserRole.xor(viceCheafRole);
            toUserRole.or(cheafRole);
        }
        // 如果为普通成员，"或"得到最终
        else if ((toUserRole.getRid() & EgRole.MEMBER) > 0) {
            toUserRole.or(cheafRole);
        }
        // 更新被移交成员的角色和权限信息
        toUser = memberService.update(fid, toUser.getId(), toUserRole.getRid(), toUserRole.getPurview());
        if (toUser == null) {
            throw new RuntimeException("移交门派帮主失败！");
        }
        return true;
    }

    /**
     * 门派账户充值
     * 
     * @param jAcount
     * @param fAcount
     * @param faction
     * @param bt
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Boolean recharge(EgAcount jAcount, EgAcount fAcount, EgFaction faction, Integer bt) throws Exception {
        // 确保江湖账户资金充足
        if (jAcount.getBt() - bt < 0) {
            throw new RuntimeException("江湖账户余额不足！");
        }
        // 江湖账户扣款
        jAcount.setBt(jAcount.getBt() - bt);
        if (acountService.update(jAcount) == null) {
            throw new RuntimeException("充值失败，请重试！");
        }
        // 门派账户充值
        fAcount.setBt(fAcount.getBt() + bt);
        if (acountService.update(fAcount) == null) {
            throw new RuntimeException("充值失败，请重试！");
        }
        // 金币流通记录
        if (btsService.create(jAcount.getId(), faction, bt, null, fAcount.getId()) == null) {
            throw new RuntimeException("充值失败，请重试！");
        }
        return true;
    }

    /**
     * 门派邀请
     * 
     * @param fid
     * @param uid
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Boolean invite(Long fid, Long uid) throws Exception {
        // 添加该用户到门派成员列表
        if (memberService.create(fid, uid) == null) {
            throw new RuntimeException("邀请失败，请重试！");
        }
        // 设置用户位置为门派,更新到用户信息表中
        if (!userService.updatePos(uid, EgOType.FACTION, fid)) {
            throw new RuntimeException("邀请失败，请重试！");
        }
        return true;
    }

    /**
     * 更新门派禅道服务地址信息
     * 
     * @param fid
     * @param serverAddress
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public String updateZtServer(Long fid, String serverAddress) throws Exception {
        EgFactionEntity entity = factionMapper.selectByPrimaryKey(fid);
        if (entity == null)
            return null;
        entity.setZtServerAddress(serverAddress);
        if (factionMapper.updateByPrimaryKey(entity) > 0 && serverAddress.trim().equals("")) {
            return serverAddress;
        }
        return null;
    }

    /**
     * 获取门派中的禅道服务地址
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    public String ztServerAddress(Long fid) throws Exception {
        EgFactionEntity entity = factionMapper.selectByPrimaryKey(fid);
        if (entity == null)
            return null;
        String result = entity.getZtServerAddress();
        if (result == null || result.trim().equals(""))
            return null;
        return result;
    }
}
